home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / conqsrc.lha / Conquest / src / combat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-20  |  12.2 KB  |  568 lines

  1. /* Combat.c: Combat commands and utilities */
  2. #include <stdio.h>
  3. #include "defs.h"
  4. #include "structs.h"
  5. #include "vars.h"
  6. #include "protos.h"
  7.  
  8. /* Player attack at star. Assumes warships and enemy planet present */
  9. void playerattack(int starnum)
  10. {
  11.   boolean battle;
  12.   char command;
  13.   struct stplanet *pplanet;
  14.  
  15.   point(33,20);
  16.   printf("Attack at star %c", starnum+'A'-1);
  17.   while (battle)
  18.   {
  19.     point(50,1);
  20.     print_star(starnum);
  21.     clear_field();
  22.     point(1,18);
  23.     printf("P?                            ");
  24.     point(3,18);
  25.  
  26.     command = get_char();
  27.     switch (command) 
  28.     {
  29.      case 'S':
  30.       starsum();
  31.       break;
  32.      case 'M': 
  33.       printmap();
  34.       break;
  35.      case 'H': 
  36.       help(3);
  37.       pause();
  38.       break;
  39.      case 'N': 
  40.       make_tf();
  41.       break;
  42.      case 'J': 
  43.       join_tf();
  44.       break;
  45.      case 'C': 
  46.       print_col();
  47.       break;
  48.      case 'R': 
  49.       ressum();
  50.       break;
  51.      case 'T': 
  52.       tfsum();
  53.       break;
  54.      case 'G': 
  55.      case ' ': 
  56.       battle = play_salvo(starnum);
  57.       break;
  58.      case 'B': 
  59.       printf("reak off attack");
  60.       battle = FALSE;
  61.       break;
  62.      default:
  63.       clear_left();
  64.       error(" !Illegal command");
  65.       break;
  66.     } /*switch */
  67.   }
  68.  
  69.   for (pplanet = stars[starnum].first_planet; pplanet; pplanet = pplanet->next)
  70.     pplanet->under_attack = false;
  71.  
  72.   point(1,24);
  73.   printf("Planet attack concluded       ");
  74.  
  75.   revolt(starnum);
  76. }
  77.  
  78. /* Battle between tf's. Assumes ships from both sides and >0 warships present*/
  79. void tf_battle(int starnum)
  80. {
  81.   int ennum, plnum, new_tf, i, dstar; 
  82.   float enodds, plodds, slist[MAX_NUM_STARS+1]; 
  83.   boolean battle, pla_loss, ene_loss, fin, first;
  84.   char ch;
  85.  
  86.   board[stars[starnum].x][ stars[starnum].y].enemy = '!';
  87.   update_board(stars[starnum].x, stars[starnum].y, left);
  88.  
  89.   ennum = 1;
  90.   while ((tf[ENEMY][ennum].dest!=starnum) ||
  91.      (tf[ENEMY][ennum].eta!=0))
  92.     ennum++;
  93.  
  94.   plnum = 1;
  95.   if (tf_stars[starnum][player]>1)
  96.   {
  97.     new_tf = get_tf(player,starnum);
  98.     for (i=1; i<=26; i++)
  99.     {
  100.       if ((tf[player][i].dest == starnum) && 
  101.       (tf[player][i].eta == 0) &&
  102.       (i != new_tf))
  103.     joinsilent(player, &tf[player][new_tf], &tf[player][i]);
  104.     }
  105.     tf_stars[starnum][player] = 1;
  106.     plnum = new_tf;
  107.   } 
  108.   else
  109.   {
  110.     while ((tf[player][plnum].dest!=starnum)||
  111.        (tf[player][plnum].eta!=0)) 
  112.       plnum++;
  113.   }
  114.  
  115.   battle = display_forces(ennum, plnum, &enodds, &plodds);
  116.  
  117.   pause();
  118.  
  119.   first = TRUE;
  120.   while (battle)
  121.   {
  122.     if (left_line[24])
  123.     {
  124.       point(1,24);
  125.       printf(blank_line);
  126.       left_line[24] = false;
  127.     }
  128.  
  129.     pla_loss = FALSE;
  130.     ene_loss = FALSE;
  131.     point(1,21);
  132.     printf(" Enemy losses:                ");
  133.     point(1,22);
  134.     printf("Player losses:                ");
  135.  
  136.     /* Fight until there are losses, but not first time */
  137.     do
  138.     {
  139.       point(15,21);
  140.       ene_loss |= lose(&tf[ENEMY][ennum].t,'t',enodds);
  141.       ene_loss |= lose(&tf[ENEMY][ennum].s,'s',enodds);
  142.       ene_loss |= lose(&tf[ENEMY][ennum].c,'c',enodds);
  143.       ene_loss |= lose(&tf[ENEMY][ennum].b,'b',enodds);
  144.       point(15,22);
  145.       pla_loss |= lose(&tf[player][plnum].t,'t',plodds);
  146.       pla_loss |= lose(&tf[player][plnum].s,'s',plodds);
  147.       pla_loss |= lose(&tf[player][plnum].c,'c',plodds);
  148.       pla_loss |= lose(&tf[player][plnum].b,'b',plodds);
  149.     }
  150.     while (!first && !ene_loss && !pla_loss);
  151.     first = FALSE;
  152.  
  153.     if (!ene_loss)
  154.     {
  155.       point(15,21);
  156.       printf("(none)");
  157.     }
  158.     if (!pla_loss)
  159.     {
  160.       point(15,22);
  161.       printf("(none)");
  162.     }
  163.  
  164.     battle = display_forces(ennum,plnum,&enodds,&plodds);
  165.  
  166.     if (battle)
  167.     {
  168.       /* Withdraw the bad guys */
  169.       new_tf = get_tf(ENEMY,starnum);
  170.       if ((tf[player][plnum].c>0) || (tf[player][plnum].b>0))
  171.       {
  172.     tf[ENEMY][new_tf].t = tf[ENEMY][ennum].t;
  173.     tf[ENEMY][new_tf].s = tf[ENEMY][ennum].s;
  174.  
  175.     if (best_withdraw_plan(starnum, enodds))
  176.     {
  177.       tf[ENEMY][new_tf].c = tf[ENEMY][ennum].c;
  178.       tf[ENEMY][new_tf].b = tf[ENEMY][ennum].b;
  179.     }
  180.       }
  181.  
  182.       /* If any need to be withdrawn */
  183.       if((tf[ENEMY][new_tf].t + tf[ENEMY][new_tf].s +
  184.       tf[ENEMY][new_tf].c + tf[ENEMY][new_tf].b) > 0) 
  185.       {
  186.     /* Find a place to withdraw to */
  187.     get_stars(starnum,slist);
  188.     do
  189.     {
  190.       dstar = rnd(nstars);
  191.     } 
  192.     while (slist[dstar] <= 0);
  193.  
  194.     tf[ENEMY][new_tf].dest = dstar;
  195.     tf[ENEMY][new_tf].eta = (int)((slist[dstar]-0.01)/vel[ENEMY])+1;
  196.     tf[ENEMY][new_tf].xf=stars[starnum].x;
  197.     tf[ENEMY][new_tf].yf=stars[starnum].y;
  198.       } 
  199.       else 
  200.     tf[ENEMY][new_tf].dest = 0;
  201.       
  202.       fin = false;
  203.       do
  204.       {
  205.     point(1,18);
  206.     printf("B?                            ");
  207.     point(3,18);
  208.     ch = get_char();
  209.     switch ( ch ) 
  210.     {
  211.      case 'M':
  212.       printmap();
  213.       break;
  214.      case 'H': 
  215.       help(2);
  216.       break;
  217.      case 'S':
  218.       starsum();
  219.       break;
  220.      case 'T': 
  221.       tfsum();
  222.       break;
  223.      case 'C':
  224.       print_col();
  225.       break;
  226.      case '?': 
  227.       break;
  228.      case 'R':
  229.       ressum();
  230.       break;
  231.      case 'O': 
  232.       battle = display_forces(ennum,plnum,&enodds, &plodds);
  233.       break;
  234.      case 'W': 
  235.       withdraw(starnum,plnum);
  236.       battle = display_forces(ennum,plnum,&enodds,&plodds);
  237.       break;
  238.      case ' ': 
  239.      case 'G': 
  240.       fin = true;
  241.       break;
  242.      default: 
  243.       printf("!illegal command");
  244.     } /*switch (*/
  245.       } 
  246.       while (!fin && battle);
  247.  
  248.       zero_tf(ENEMY,new_tf);
  249.       zero_tf(player,plnum);
  250.  
  251.       if (tf[ENEMY][new_tf].dest != 0) 
  252.       {
  253.     point(1, 23);
  254.     printf("en withdraws");
  255.     point(14, 23);
  256.     disp_tf(&tf[ENEMY][new_tf]);
  257.  
  258.     tf[ENEMY][ennum].t = tf[ENEMY][ennum].t - tf[ENEMY][new_tf].t;
  259.     tf[ENEMY][ennum].s = tf[ENEMY][ennum].s - tf[ENEMY][new_tf].s;
  260.     tf[ENEMY][ennum].c = tf[ENEMY][ennum].c - tf[ENEMY][new_tf].c;
  261.     tf[ENEMY][ennum].b = tf[ENEMY][ennum].b - tf[ENEMY][new_tf].b;
  262.  
  263.     zero_tf(ENEMY,ennum);
  264.  
  265.     battle = display_forces (ennum, plnum, &enodds, &plodds);
  266.       }
  267.     }
  268.   }
  269.  
  270.   zero_tf(ENEMY, ennum);
  271.   zero_tf(player, plnum);
  272.  
  273.   revolt(starnum);
  274.  
  275.   on_board(stars[starnum].x, stars[starnum].y);
  276. }
  277.  
  278. void withdraw(int starnum, int plnum)
  279. {
  280.   int withnum;
  281.   boolean error;
  282.  
  283.   printf("ithdraw ");
  284.   clear_left();
  285.   point(1,19);
  286.   withnum = split_tf(plnum);
  287.  
  288.   if ( tf[player][withnum].dest != 0 ) 
  289.   {
  290.     point(1,20);
  291.     error = set_des(withnum);
  292.     if (error) 
  293.     {
  294.       tf[player][plnum].dest = starnum;
  295.       joinsilent(player, &tf[player][plnum], &tf[player][withnum]);
  296.       tf_stars[starnum][player] = 1;
  297.     } 
  298.     else
  299.       /* FOO: Shouldn't this be a return code? Or is it used otherwhere */
  300.       tf[player][withnum].withdrew = true;
  301.   }
  302. }
  303.  
  304. void blast(tplanet *planet, int factors)
  305. {
  306.   int killed;
  307.   
  308.   killed = min(planet->capacity,factors / 4);
  309.  
  310.   planet->inhabitants = min(planet->inhabitants, planet->capacity) - killed;
  311.   planet->iu = min(planet->iu - killed, planet->inhabitants * iu_ratio);
  312.   planet->capacity = planet->capacity - killed;
  313.  
  314.   /* Totally destroyed... */
  315.   if (planet->inhabitants <= 0) 
  316.   {
  317.     planet->inhabitants = 0;
  318.     planet->iu = 0;
  319.     planet->mb = 0;
  320.     planet->amb = 0;
  321.  
  322.     if (planet->team != none)
  323.     {
  324.       col_stars[planet->pstar][planet->team]--;
  325.  
  326.       planet->team = none;
  327.       planet->esee_team = none;
  328.       planet->conquered = false;
  329.  
  330.       on_board(stars[planet->pstar].x, stars[planet->pstar].y);
  331.     }
  332.   }
  333. }
  334.  
  335. void fire_salvo(tteam att_team, int tfnum, struct stplanet *planet,
  336.         boolean first_time)
  337. {
  338.   int bases, att_forces, def_forces; 
  339.   boolean a_losses, p_losses;
  340.   float att_odds, def_odds, attack_save, defend_save;
  341.   tteam def_team;
  342.   struct sttf *task = &tf[att_team][tfnum];
  343.  
  344.   if (left_line[24]) 
  345.   {
  346.     point(1,24);
  347.     printf(blank_line);
  348.     left_line[24] = false;
  349.   }
  350.  
  351.   if (att_team == ENEMY)
  352.     def_team = player;
  353.   else
  354.     def_team = ENEMY;
  355.  
  356.   att_forces = weapons[att_team]*(task->c*c_guns + task->b*b_guns);
  357.   def_forces = weapons[def_team]*(planet->mb*c_guns+planet->amb*b_guns);
  358.  
  359.   if (def_forces > 0)
  360.   {
  361.     att_odds = fmin((((float) def_forces) / att_forces), 14.0);
  362.     attack_save = exp(log(0.8) * (att_odds));
  363.     def_odds = fmin((float)att_forces/def_forces, 14.0);
  364.     defend_save=exp(log(0.8)* (def_odds));
  365.  
  366.     point(1,20);
  367.     if (att_team == player)
  368.       printf("TF%c", tfnum+'a'-1);
  369.     else
  370.       printf(" EN");
  371.     printf(": %4d(weap %2d)sur: %4.0f", att_forces, 
  372.        weapons[att_team], attack_save*100);
  373.  
  374.     point(1,21);
  375.     printf(" %c%d:%4d (weap %2d)sur: %4.0f", planet->pstar+'A'-1, 
  376.        planet->number, def_forces, weapons[def_team], defend_save*100);
  377.  
  378.     point(1,22);
  379.     printf("Attacker losses:              ");
  380.     point(1,23);
  381.     left_line[23]=true;
  382.     printf(" Planet losses :              ");
  383.  
  384.     a_losses = FALSE;
  385.     p_losses = FALSE;
  386.  
  387.     do 
  388.     {
  389.       point(17,22);
  390.       a_losses |= lose(&task->c, 'c', attack_save);
  391.       a_losses |= lose(&task->b, 'b', attack_save);
  392.  
  393.       point(17,23);
  394.       bases = planet->mb;
  395.       p_losses |=lose(&planet->mb, 'm', defend_save);
  396.       if ( planet->mb != bases ) printf("b");
  397.  
  398.       bases = planet->amb;
  399.       p_losses |= lose(&planet->amb,'a',defend_save);
  400.       if ( planet->amb != bases ) printf("mb");
  401.     } 
  402.     while (!first_time && !p_losses && a_losses);
  403.  
  404.     if (!a_losses) 
  405.     {
  406.       point(17,22);
  407.       printf("(none)");
  408.     }
  409.  
  410.     if (!p_losses) 
  411.     {
  412.       point(17,23);
  413.       printf("(none)");
  414.     }
  415.   }
  416.  
  417.   if ((planet->mb+planet->amb == 0) && (any_bc(att_team, planet->pstar)))
  418.   {
  419.     point(1,24);
  420.     printf("Planet %d falls!               ", planet->number);
  421.  
  422.     planet->team = att_team;
  423.     planet->esee_team = att_team;
  424.     planet->conquered = true;
  425.  
  426.     col_stars[task->dest][def_team]--;
  427.     col_stars[task->dest][att_team]++;
  428.  
  429.     point(50,1);
  430.     print_star(planet->pstar);
  431.  
  432.     clear_field();
  433.  
  434.     on_board(stars[task->dest].x, stars[task->dest].y);
  435.   }
  436. }
  437.  
  438. /* Play attack at star. Assumes warships & enemy planet present */
  439. /* Returns TRUE if there is still a battle going on */
  440. boolean play_salvo(int starnum)
  441. {
  442.   int planet_num, tf_num; 
  443.   boolean first_time;
  444.   struct stplanet *pplanet;
  445.   
  446.   printf("Attack planet ");
  447.  
  448.   pplanet = stars[starnum].first_planet;
  449.  
  450.   /* If more than one enemy planet, we have to ask which one */
  451.   if ((col_stars[starnum][ENEMY]>1))
  452.   {
  453.     printf(":");
  454.     planet_num = get_char() - '0';
  455.     clear_left();
  456.  
  457.     for (;(pplanet->number != planet_num) && (pplanet->next);
  458.      pplanet = pplanet->next)
  459.       ;
  460.  
  461.     if (pplanet->number != planet_num)
  462.     {
  463.       error("! That is not a useable planet");
  464.       return(TRUE);
  465.     } 
  466.     if (pplanet->team != ENEMY)
  467.     {
  468.       error(" !Not an enemy colony");
  469.       return(TRUE);
  470.     }
  471.   } 
  472.   else 
  473.   {
  474.     while (pplanet->team != ENEMY)
  475.       pplanet = pplanet->next;
  476.  
  477.     printf("%d", pplanet->number);
  478.     clear_left();
  479.   }
  480.  
  481.   /* Find out which tf is attacking */
  482.   point(1,19);
  483.   printf(" attacking tf ");
  484.  
  485.   if (tf_stars[starnum][player]>1) 
  486.   {
  487.     printf(":");
  488.     tf_num = get_char() - 'A' + 1;
  489.  
  490.     if ((tf_num < 1) || (tf_num > 26))
  491.     {
  492.       error(" !Illegal tf");
  493.       return(TRUE);
  494.     }
  495.  
  496.     if (tf[player][tf_num].dest == 0)
  497.     {
  498.       error(" !Nonexistent tf");
  499.       return(TRUE);
  500.     }
  501.  
  502.     if ((tf[player][tf_num].dest!=starnum) || (tf[player][tf_num].eta!=0))
  503.     {
  504.       error(" !Tf is not at this star      ");
  505.       return(TRUE);
  506.     }
  507.  
  508.     if ((tf[player][tf_num].b+tf[player][tf_num].c) == 0)
  509.     {
  510.       error(" !Tf has no warships");
  511.       return(TRUE);
  512.     }
  513.   } 
  514.   else 
  515.   {
  516.     /* Only one TF - must be the one with warships */
  517.     tf_num = 1;
  518.     while ((tf[player][tf_num].dest != starnum) ||
  519.        (tf[player][tf_num].eta != 0))
  520.       tf_num++;
  521.  
  522.     putchar(tf_num+'a'-1);
  523.   }
  524.  
  525.   first_time = !pplanet->under_attack;
  526.   if (!(pplanet->under_attack))
  527.   {
  528.     pplanet->under_attack = true;
  529.     point(50,1);
  530.     print_star(starnum);
  531.     clear_field();
  532.   }
  533.   fire_salvo(player, tf_num, pplanet, first_time);
  534.   zero_tf(player,tf_num);
  535.  
  536.   return((col_stars[starnum][ENEMY]>0) && any_bc(player,starnum));
  537. }
  538.  
  539. void battle()
  540. {
  541.   boolean first;
  542.   int starnum;
  543.  
  544.   first = true;
  545.   for (starnum = 1; starnum <= NUM_STARS; starnum++)
  546.   {
  547.     if ((tf_stars[starnum][ENEMY] > 0) &&
  548.     (tf_stars[starnum][player] > 0) &&
  549.     (any_bc(ENEMY, starnum) || any_bc(player, starnum)))
  550.     {
  551.       if (first) 
  552.       {
  553.     point(33,20);
  554.     printf("* Tf battle *   ");
  555.     first = false;
  556.       }
  557.       tf_battle(starnum);
  558.     }
  559.  
  560.     /* By now we know there is only one side left with warships here */
  561.     if ((any_bc(ENEMY,starnum)) && (col_stars[starnum][player] > 0))
  562.       enemy_attack(starnum);
  563.  
  564.     if ((any_bc(player, starnum)) && (col_stars[starnum][ENEMY] > 0))
  565.       playerattack(starnum);
  566.   }
  567. }
  568.